package com.ayf.payment.game.api.controller;

import com.alibaba.fastjson.JSON;
import cn.hutool.core.lang.Validator;
import com.ayf.payment.game.api.Template.TemplateUtils;
import com.ayf.payment.game.api.cache.redis.RedisCacheUtil;
import com.ayf.payment.game.api.channel.alipay.service.AliPayService;
import com.ayf.payment.game.api.dto.*;
import com.ayf.payment.game.api.dto.alipay.AliOrderStatus;
import com.ayf.payment.game.api.dto.alipay.MerchantAlipayOrderDTO;
import com.ayf.payment.game.api.dto.criteria.*;
import com.ayf.payment.game.api.dto.platform.MerchantCashOutCountDTO;
import com.ayf.payment.game.api.dto.platform.MerchantCashOutDTO;
import com.ayf.payment.game.api.dto.platform.NetConfigDTO;
import com.ayf.payment.game.api.dto.platform.criteria.MerchantBalanceRecordCriteria;
import com.ayf.payment.game.api.dto.platform.criteria.MerchantCashOutCriteria;
import com.ayf.payment.game.api.dto.platform.criteria.MerchantCashOutPageCriteria;
import com.ayf.payment.game.api.entity.*;
import com.ayf.payment.game.api.entity.platform.*;
import com.ayf.payment.game.api.exception.LogicalException;
import com.ayf.payment.game.api.exception.ParameterException;
import com.ayf.payment.game.api.service.*;
import com.ayf.payment.game.api.service.platform.*;
import com.ayf.payment.game.api.sms.SMSUtil;
import com.ayf.payment.game.api.type.CommonConstants;
import com.ayf.payment.game.api.type.LoginType;
import com.ayf.payment.game.api.type.SMSType;
import com.ayf.payment.game.api.utils.*;
import com.ayf.payment.game.api.utils.Base64;
import com.ayf.payment.game.api.wx.WxSendMsgUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.swwx.charm.commons.lang.utils.BeanConvertUtils;
import com.swwx.charm.commons.lang.utils.LogPortal;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.thymeleaf.context.Context;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Description: 商户控制层
 * @Author: zh-liang
 * @Date : 2019-12-16 15:36
 */
@RestController
@RequestMapping("/v/merchant")
public class MerchantController {

    @Autowired
    private MerchantService merchantService;

    @Autowired
    private LoginHistoryService loginHistoryService;

    @Autowired
    private MerchantConfigService merchantConfigService;

    @Autowired
    private IpWhiteListService ipWhiteListService;

    @Autowired
    private MerchantAccountService merchantAccountService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private RedisCacheUtil redisCacheUtil;

    @Autowired
    private SystemBulletinService systemBulletinService;

    @Autowired
    private MerchantBalanceRecordService merchantBalanceRecordService;

    @Autowired
    private MerchantCashOutService merchantCashOutService;

    @Autowired
    private MerchantSettleRateCustomService merchantSettleRateCustomService;

    @Autowired
    private PartitionService partitionService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private NetConfigService netConfigService;

    @Autowired
    private NetRechargeUrlService netRechargeUrlService;

    @Autowired
    private TemplateUtils templateUtils;


    @Autowired
    private SMSUtil smsUtil;

    @Autowired
    private MerchantPermissionService merchantPermissionService;
    @Autowired
    private WxSendMsgUtils wxSendMsgUtils;
    @Autowired
    private WxUserService wxUserService;
    @Autowired
    private WxQrCodeService wxQrCodeService;
    @Autowired
    private WxConfigService wxConfigService;
    @Autowired
    private MerchantSonService merchantSonService;
    @Autowired
    private MerchantAlipayConfigService merchantAlipayConfigService;
    @Autowired
    private MerchantAlipayOrderService merchantAlipayOrderService;
    @Autowired
    private AliPayService aliPayService;
    @Autowired
    private LogOperationService logOperationService;

    @Value("${XY_RECHARGE_GATEWAY_PATH}")
    private String xyRechargeGateWayPath;

    /**
     * 商户注册
     *
     * @param merchantCriteria
     * @return
     */
    @PostMapping("/register")
    public CommonResult<Boolean> register(@RequestBody MerchantCriteria merchantCriteria) {
        if (merchantCriteria == null) {
            throw new ParameterException("注册信息不能为空");
        }
        if (StringUtils.isBlank(merchantCriteria.getPhone())) {
            throw new ParameterException("手机不能为空");
        }
        if (StringUtils.isBlank(merchantCriteria.getQq())) {
            throw new ParameterException("QQ不能为空");
        }
//        if (StringUtils.isBlank(merchantCriteria.getCode())) {
//            throw new ParameterException("短信验证码不能为空");
//        }
//        String code = redisCacheUtil.getObjectFromCache(SMSType.REGISTER.name() + merchantCriteria.getPhone());
//        if (!merchantCriteria.getCode().equalsIgnoreCase(code)) {
//            return new CommonResult<>(CommonConstants.RETURN_ERROR, "注册失败，短信验证码输入错误");
//        }
        if (merchantService.register(merchantCriteria)) {
            return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "注册成功");
        } else {
            return new CommonResult<>(CommonConstants.RETURN_ERROR, "注册失败");
        }
    }

    /**
     * 登录
     *
     * @param merchantCriteria
     * @return
     */
    @PostMapping("/login")
    public CommonResult<Map<String, Object>> login(@RequestBody MerchantCriteria merchantCriteria, HttpServletRequest request) {
        String ip = IPUtils.getIp(request);
        MerchantLoginDTO loginDTO = merchantService.login(merchantCriteria);
        if (loginDTO.getType().equals(LoginType.FATHER.name())) {
            String loginType = "账号密码登录";
            MerchantDTO merchant = loginDTO.getMerchant();
            if (StringUtils.isNotBlank(merchantCriteria.getLoginType()) && merchantCriteria.getLoginType().equals("sms")) {
                if (StringUtils.isBlank(merchantCriteria.getCode())) {
                    throw new ParameterException("短信验证码不能为空");
                }
                String code = redisCacheUtil.getObjectFromCache(SMSType.LOGIN.name() + merchant.getPhone());
                if (!merchantCriteria.getCode().equalsIgnoreCase(code)) {
                    return new CommonResult<>(CommonConstants.RETURN_ERROR, "登录失败，短信验证码输入错误");
                }
                IpWhiteList one = ipWhiteListService.selectOne(merchant.getId());
                //判断登录ip是否在ip白名单
                if (StringUtils.isNotEmpty(one.getIp())) {
                    if ("0".equals(one.getIp())) {
                        return new CommonResult<>(304, "登录失败，只允许微信扫码登录");
                    }
                }
                loginType = "账号密码-短信验证登录";
            } else if (merchant.getSmsStatus() == 1) {
                Map<String, Object> result = new HashMap<>(16);
                result.put("phone", SensitiveDataUtil.mobileEncrypt(merchant.getPhone()));
                IpWhiteList one = ipWhiteListService.selectOne(merchant.getId());
                if (StringUtils.isBlank(one.getIp())) {
                    return new CommonResult<>(303, "登录失败，请在【账户管理】-【账户安全】配置授权IP", result);
                }
                //判断登录ip是否在ip白名单
                if (StringUtils.isNotEmpty(one.getIp())) {
                    if ("0".equals(one.getIp())) {
                        return new CommonResult<>(304, "登录失败，只允许微信扫码登录", result);
                    }
                    if (!one.getIp().contains(ip)) {
                        return new CommonResult<>(303, "登录失败，请在【账户管理】-【账户安全】配置授权IP", result);
                    }
                }
                loginType = "账号密码-ip白名单登录";
            }
            //redis保存登录id
            Map<String, Object> result = saveFatherLogin(request, merchant);
            wxSendMsgUtils.login(merchant.getId(), merchant.getId(), merchantCriteria.getLoginAccount(), loginType,ip);
            return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "登录成功", result);
        } else if (loginDTO.getType().equals(LoginType.SON.name())) {
            MerchantSonDTO merchantSon = loginDTO.getMerchantSon();
            Map<String, Object> result = saveSonLogin(request, merchantSon);
            wxSendMsgUtils.login(merchantSon.getMerchantId(), merchantSon.getId(), merchantCriteria.getLoginAccount()
                    , "账号密码登录",ip);
            return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "登录成功", result);
        } else {
            return new CommonResult<>(CommonConstants.RETURN_ERROR, "登录失败", null);
        }
    }

    /**
     * 登录
     *
     * @param merchantCriteria
     * @return
     */
    @PostMapping("/loginClient")
    public CommonResult<Map<String, Object>> loginClient(@RequestBody MerchantCriteria merchantCriteria, HttpServletRequest request) {

        MerchantLoginDTO loginDTO = merchantService.login(merchantCriteria);
        MerchantDTO merchant = loginDTO.getMerchant();
        //redis保存登录id
        Map<String, Object> result = saveFatherClientLogin(request, merchant);
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "登录成功", result);
    }

    public void addLoginHistory(Integer merchantId, HttpServletRequest request) {
        String ip = IPUtils.getIp(request);
        LoginHistory loginHistory = new LoginHistory();
        loginHistory.setLoginIp(ip);
        loginHistory.setLoginCity("未知");
        loginHistory.setMerchantId(merchantId);
        loginHistory.setLoginTime(new Date());
        String system = "其它";
        String agent = request.getHeader("user-agent");
        if (agent.contains("Windows")) {
            system = "Windows客户端";
        } else if (agent.contains("Mac")) {
            system = "Mac客户端";
        } else if (agent.contains("Android")) {
            system = "Android移动客户端";
        } else if (agent.contains("iPad")) {
            system = "iPad客户端";
        } else if (agent.contains("iPhone")) {
            system = "iPhone移动客户端";
        }
        loginHistory.setLoginSystem(system);
        //增加登录记录
        loginHistoryService.insert(loginHistory);

        // 更新商户的最后一次登录时间
        Merchant merchant = new Merchant();
        merchant.setId(merchantId);
        merchant.setLoginTime(DateUtils.getNowDate());
        merchantService.update(merchant);
    }

    /**
     * 退出登录
     *
     * @param merchantDTO
     * @return
     */
    @PostMapping("/logout")
    public CommonResult<String> logout(MerchantDTO merchantDTO) {
        tokenService.deleteTokenByToken(merchantDTO.getToken());
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "退出登录成功", null);
    }

    /**
     * 获取商户后台主商户权限列表
     *
     * @param merchantDTO
     * @return
     */
    @PostMapping("/getMerchantMenu")
    public CommonResult<?> getMerchantMenu(MerchantDTO merchantDTO) {
        if (LoginType.FATHER.name().equals(merchantDTO.getLoginType())) {
            MerchantPermissionDTO adminList = merchantPermissionService.adminList(merchantDTO.getMerchantType());
            return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "主商户权限列表查询成功", adminList);
        } else {
            MerchantSon merchantSon = merchantSonService.selectInfo(merchantDTO.getLoginId());
            MerchantPermissionDTO dto = merchantPermissionService.sonPermissionList(merchantSon.getRoleId());
            return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "主商户权限列表查询成功", dto);
        }
    }

    /**
     * 忘记密码
     *
     * @param merchantCriteria
     * @return
     */
    @PostMapping("/resetPassword")
    public CommonResult resetPassword(@RequestBody MerchantCriteria merchantCriteria) {
        if (StringUtils.isBlank(merchantCriteria.getPhone())) {
            throw new ParameterException("手机号不能为空");
        }
        if (StringUtils.isBlank(merchantCriteria.getCode())) {
            throw new ParameterException("短信验证码不能为空");
        }
        if (StringUtils.isBlank(merchantCriteria.getLoginAccount())) {
            throw new ParameterException("登录账号不能为空");
        }
        String code = redisCacheUtil.getObjectFromCache(SMSType.RESET_PASSWORD.name() + merchantCriteria.getPhone());
        Merchant merchant = new Merchant();
        merchant.setLoginAccount(merchantCriteria.getLoginAccount());
        MerchantDTO merchantDTO = merchantService.selectOne(merchant);
        if (merchantDTO == null) {
            throw new ParameterException("该商户不存在，请确认登录账号");
        }
        if (StringUtils.isBlank(merchantDTO.getPhone())) {
            throw new ParameterException("手机号验证错误，该商户尚未绑定手机号");
        }
        if (!merchantDTO.getPhone().equals(merchantCriteria.getPhone())) {
            throw new ParameterException("手机号验证错误，请使用" + SensitiveDataUtil.mobileEncrypt(merchantDTO.getPhone()) + "重置密码");
        }
        if (!merchantCriteria.getCode().equalsIgnoreCase(code)) {
            return new CommonResult(CommonConstants.RETURN_ERROR, "短信验证码输入错误");
        }
        if (merchantService.resetPassword(merchantCriteria)) {
            tokenService.deleteTokenByLoginId(merchantCriteria.getId(),merchantCriteria.getId());
            return new CommonResult(CommonConstants.RETURN_SUCCESS, "修改密码成功");
        }
        return new CommonResult(CommonConstants.RETURN_ERROR, "修改密码失败");
    }

    /**
     * 商户修改登录密码
     *
     * @param merchantCriteria
     * @return
     */
    @PostMapping("/updatePassword")
    public CommonResult<Boolean> updatePassword(@RequestBody MerchantCriteria merchantCriteria, MerchantDTO merchantDTO) {
        merchantCriteria.setId(merchantDTO.getId());
        if (merchantService.updatePassword(merchantCriteria)) {
            tokenService.deleteTokenByLoginId(merchantCriteria.getId(), merchantCriteria.getId());
            return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "修改密码成功", true);
        }
        return new CommonResult<>(CommonConstants.RETURN_ERROR, "修改密码失败", false);
    }

    /**
     * 商户修改支付密码
     *
     * @param merchantCriteria
     * @param merchantDTO
     * @return
     */
    @PostMapping("/updatePayPassword")
    public CommonResult<Boolean> updatePayPassword(@RequestBody MerchantCriteria merchantCriteria, MerchantDTO merchantDTO) {
        merchantCriteria.setId(merchantDTO.getId());
        if (merchantService.updatePayPassword(merchantCriteria)) {
            return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "修改支付密码成功", true);
        }
        return new CommonResult<>(CommonConstants.RETURN_ERROR, "修改支付密码失败", false);
    }

    /**
     * 查询出商户基本信息
     *
     * @param merchantDTO
     * @return
     */
    @PostMapping("/selectOne")
    public CommonResult<MerchantDTO> selectOne(MerchantDTO merchantDTO) {
        Merchant merchant = new Merchant();
        merchant.setId(merchantDTO.getId());
        MerchantDTO dto = merchantService.selectOne(merchant);
        dto.setPhone(SensitiveDataUtil.mobileEncrypt(dto.getPhone()));
        dto.setPrivateKey(null);
        dto.setGameCashPublicKey(null);
        MerchantConfig merchantConfig = merchantConfigService.selectOne(merchantDTO.getId());
        if (Objects.nonNull(merchantConfig)){
            dto.setDomainName(merchantConfig.getDomainName());
            dto.setNetName(merchantConfig.getNetName());
        }
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "查询成功", dto);
    }

    /**
     * 修改商户基本信息
     *
     * @param dto
     * @param merchantDTO
     * @return
     */
    @PostMapping("/update")
    public CommonResult update(@RequestBody MerchantDTO dto, MerchantDTO merchantDTO) {
        Merchant merchant = new Merchant();
        merchant.setId(merchantDTO.getId());
        if (StringUtils.isNotEmpty(dto.getName())) {
            merchant.setName(dto.getName());
        }
        if (StringUtils.isNotEmpty(dto.getQq())) {
            merchant.setQq(dto.getQq());
        }
        if (dto.getSmsStatus() != null) {
            merchant.setSmsStatus(dto.getSmsStatus());
        }
        merchant.setEmail(dto.getEmail());
        merchant.setIdCardValidityTimeType(dto.getIdCardValidityTimeType());
        merchant.setIdCard(dto.getIdCard());
        merchant.setBusinessAddressAreaCode(dto.getBusinessAddressAreaCode());
        merchant.setBusinessAddressAreaName(dto.getBusinessAddressAreaName());
        merchant.setBusinessAddressCityCode(dto.getBusinessAddressCityCode());
        merchant.setBusinessAddressCityName(dto.getBusinessAddressCityName());
        merchant.setBusinessAddressProvinceCode(dto.getBusinessAddressProvinceCode());
        merchant.setBusinessAddressProvinceName(dto.getBusinessAddressProvinceName());
        merchant.setIdCardBackImg(dto.getIdCardBackImg());
        merchant.setIdCardFrontImg(dto.getIdCardFrontImg());
        merchant.setIdCardValidityTimeStart(dto.getIdCardValidityTimeStart());
        merchant.setIdCardValidityTimeEnd(dto.getIdCardValidityTimeEnd());
        merchant.setDetailAddress(dto.getDetailAddress());

        MerchantConfig merchantConfig = new MerchantConfig();
        merchantConfig.setMerchantId(merchantDTO.getId());
        merchantConfig.setNetName(dto.getNetName());
        merchantConfig.setDomainName(dto.getDomainName());
        if (merchantService.updateMerchantAndMerchantConfig(merchant,merchantConfig)) {
            return new CommonResult(CommonConstants.RETURN_SUCCESS, "更新成功", null);
        }
        return new CommonResult(CommonConstants.RETURN_ERROR, "更新失败", null);
    }

    /**
     * 查询商户配制信息
     *
     * @param merchantDTO
     * @return
     */
    @PostMapping("/selectConfig")
    public CommonResult<MerchantConfig> s(MerchantDTO merchantDTO) {
        MerchantConfig merchantConfig = merchantConfigService.selectOne(merchantDTO.getId());
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "查询商户配置信息成功", merchantConfig);
    }

    /**
     * 修改客服信息
     *
     * @param merchantConfig
     * @param merchantDTO
     * @return
     */
    @PostMapping("updateQQ")
    public CommonResult updateQQ(@RequestBody MerchantConfig merchantConfig, MerchantDTO merchantDTO) {
        merchantConfig.setMerchantId(merchantDTO.getId());
        if (merchantConfigService.updateQQ(merchantConfig)) {
            return new CommonResult(CommonConstants.RETURN_SUCCESS, "修改成功", null);
        }
        return new CommonResult(CommonConstants.RETURN_ERROR, "修改失败", null);
    }

    /**
     * 更新玩家积分状态
     *
     * @param merchantConfig
     * @param merchantDTO
     * @return
     */
    @PostMapping("updatePlayerIntegralStatus")
    public CommonResult<Object> updatePlayerIntegralStatus(@RequestBody MerchantConfig merchantConfig,
    MerchantDTO merchantDTO) {
        merchantConfig.setMerchantId(merchantDTO.getId());
        if (merchantConfigService.updatePlayerIntegralStatus(merchantConfig)) {
            return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "修改成功", null);
        }
        return new CommonResult<>(CommonConstants.RETURN_ERROR, "修改失败", null);
    }

    /**
     * 修改留言箱状态
     *
     * @param merchantConfig
     * @param merchantDTO
     * @return
     */
    @PostMapping("updateBoxStatus")
    public CommonResult updateMessageBoxStatus(@RequestBody MerchantConfig merchantConfig, MerchantDTO merchantDTO) {
        merchantConfig.setMerchantId(merchantDTO.getId());
        if (merchantConfigService.updateMessageBoxStatus(merchantConfig)) {
            return new CommonResult(CommonConstants.RETURN_SUCCESS, "留言箱状态修改成功", null);
        }
        return new CommonResult(CommonConstants.RETURN_ERROR, "留言箱状态修改失败", null);
    }

    /**
     * 修改最小充值金额
     *
     * @param merchantConfig
     * @param merchantDTO
     * @return
     */
    @PostMapping("updateMinRechargeAmount")
    public CommonResult updateMinRechargeAmount(@RequestBody MerchantConfig merchantConfig, MerchantDTO merchantDTO) {
        merchantConfig.setMerchantId(merchantDTO.getId());
        if (merchantConfigService.updateMinRechargeAmount(merchantConfig)) {
            return new CommonResult(CommonConstants.RETURN_SUCCESS, "最小充值金额修改成功", null);
        }
        return new CommonResult(CommonConstants.RETURN_ERROR, "最小充值金额修改失败", null);
    }

    /**
     * 更新商户密匙对
     *
     * @param merchantDTO
     * @return
     */
    @PostMapping("/updateKey")
    public CommonResult updateKey(MerchantDTO merchantDTO) {
        Merchant merchant = new Merchant();
        merchant.setId(merchantDTO.getId());
        Map<String, String> key = KeyUtil.genKey();
        merchant.setPublicKey(key.get(KeyUtil.PUBLIC_KEY));
        merchant.setPrivateKey(key.get(KeyUtil.PRIVATE_KEY));
        if (merchantService.update(merchant)) {
            return new CommonResult(CommonConstants.RETURN_SUCCESS, "更新密匙对成功");
        }
        return new CommonResult(CommonConstants.RETURN_ERROR, "更新密匙对失败");
    }

    /**
     * 更新商户密匙对
     *
     * @param merchantDTO
     * @return
     */
    @PostMapping("/updateGameKey")
    public CommonResult updateGameKey(MerchantDTO merchantDTO) {
        Merchant merchant = new Merchant();
        merchant.setId(merchantDTO.getId());
        Map<String, String> key = KeyUtil.genKey();
        merchant.setGameCashPublicKey(key.get(KeyUtil.PUBLIC_KEY));
        merchant.setGameCashPrivateKey(key.get(KeyUtil.PRIVATE_KEY));
        if (merchantService.update(merchant)) {
            return new CommonResult(CommonConstants.RETURN_SUCCESS, "更新密匙对成功");
        }
        return new CommonResult(CommonConstants.RETURN_ERROR, "更新密匙对失败");
    }

    /**
     * 商户登录记录查询
     *
     * @param merchantDTO
     * @return
     */
    @PostMapping("/history")
    public CommonResult<PageDTO> loginHistory(@RequestBody LoginHistoryCriteria loginHistoryCriteria,
                                              MerchantDTO merchantDTO) {
        LoginHistory loginHistory = new LoginHistory();
        loginHistory.setMerchantId(merchantDTO.getId());
        PageHelper.startPage(loginHistoryCriteria.getPageNum(), loginHistoryCriteria.getPageSize());
        List<LoginHistory> historyList = loginHistoryService.selectAll(loginHistory);
        PageInfo<LoginHistory> pageInfo = new PageInfo(historyList);
        PageDTO dto = BeanConvertUtils.convert(pageInfo, PageDTO.class);
        return new CommonResult<PageDTO>(CommonConstants.RETURN_SUCCESS, "登录记录查询成功", dto);
    }

    /**
     * 查看商户ip白名单
     *
     * @param merchantDTO
     * @return
     */
    @PostMapping("/selectIpWhite")
    public CommonResult<IpWhiteList> selectIpWhite(MerchantDTO merchantDTO) {
        IpWhiteList one = ipWhiteListService.selectOne(merchantDTO.getId());
        return new CommonResult<IpWhiteList>(CommonConstants.RETURN_SUCCESS, "查询IP白名单成功", one);
    }

    /**
     * 更新IP白名单
     *
     * @param ipWhiteList
     * @return
     */
    @PostMapping("/updateIpWhite")
    public CommonResult updateIpWhite(@RequestBody IpWhiteList ipWhiteList) {
        if (ipWhiteListService.update(ipWhiteList)) {
            return new CommonResult(CommonConstants.RETURN_SUCCESS, "更新IP白名单成功");
        }
        return new CommonResult(CommonConstants.RETURN_ERROR, "更新IP白名单失败");
    }

    /**
     * 查询商户账户信息成功
     *
     * @param merchantDTO
     * @return
     */
    @PostMapping("/selectAccount")
    public CommonResult<MerchantAccountDTO> selectAccount(MerchantDTO merchantDTO) {
        MerchantAccountDTO merchantAccount = BeanConvertUtils.convert(merchantAccountService.selectOne(merchantDTO.getId()),MerchantAccountDTO.class);
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "查询商户账户信息成功", merchantAccount);
    }

    /**
     * 查询商户结算费率信息
     *
     * @param merchantDTO
     * @return
     */
    @PostMapping("/selectRateInfo")
    public CommonResult<List<SettleRateInfoDTO>> selectRateInfo(MerchantDTO merchantDTO) {
        List<SettleRateInfoDTO> list = merchantService.selectRateInfo(merchantDTO.getId());
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "查询商户结算费率信息成功", list);
    }

    /**
     * 更改商户结算产品状态
     *
     * @param merchantDTO
     * @return
     */
    @PostMapping("/updateProductStatus")
    public CommonResult updateProductStatus(MerchantDTO merchantDTO, @RequestBody MerchantSettleRateCustom rateCustom) {
        return new CommonResult<>(CommonConstants.RETURN_ERROR, "该操作已被禁用");
//        rateCustom.setMerchantId(merchantDTO.getId());
//        if (merchantService.updateProductStatus(rateCustom)) {
//            return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "更改商户结算产品状态成功");
//        }
//        return new CommonResult<>(CommonConstants.RETURN_ERROR, "更改商户结算产品状态失败");
    }

    /**
     * 系统公告查询
     *
     * @param pageCriteria
     * @return
     */
    @PostMapping("/bulletinList")
    public CommonResult<PageDTO> list(@RequestBody PageCriteria pageCriteria) {
        PageHelper.startPage(1, pageCriteria.getPageSize());
        List<SystemBulletin> list = systemBulletinService.list();
        PageInfo<SystemBulletin> pageInfo = new PageInfo<>(list);
        PageDTO dto = BeanConvertUtils.convert(pageInfo, PageDTO.class);
        return new CommonResult<PageDTO>(CommonConstants.RETURN_SUCCESS, "系统公告查询成功", dto);
    }

    /**
     * 账户收支记录查询
     *
     * @param criteria
     * @return
     */
    @PostMapping("/budgetList")
    public CommonResult<PageDTO> budgetList(@RequestBody MerchantBalanceRecordCriteria criteria, MerchantDTO merchantDTO) {
        PageHelper.startPage(criteria.getPageNum(), criteria.getPageSize());
        criteria.setMerchantId(merchantDTO.getId());
        List<MerchantBalanceRecord> list = merchantBalanceRecordService.select(criteria);
        PageInfo<MerchantBalanceRecord> pageInfo = new PageInfo<>(list);
        PageDTO dto = BeanConvertUtils.convert(pageInfo, PageDTO.class);
        MerchantBalanceRecord merchantBudget = merchantBalanceRecordService.selectToday(merchantDTO.getId());
        dto.getList().add(0, merchantBudget);
        return new CommonResult<PageDTO>(CommonConstants.RETURN_SUCCESS, "账户收支记录查询成功", dto);
    }

    /**
     * 提现记录查询
     *
     * @param selectCriteria
     * @param merchantDTO
     * @return
     */
    @PostMapping("/cashOutAll")
    public CommonResult<PageDTO> cashOutAll(@RequestBody MerchantCashOutPageCriteria selectCriteria, MerchantDTO merchantDTO) {
        selectCriteria.setMerchantId(merchantDTO.getId());
        PageHelper.startPage(selectCriteria.getPageNum(), selectCriteria.getPageSize());
        List<MerchantCashOutDTO> list = merchantCashOutService.selectMerchantCashOutAll(selectCriteria);
        if (CollectionUtils.isEmpty(list)){
            list = new ArrayList<>();
        }
        for (MerchantCashOutDTO dto : list) {
            dto.setCardNo(SensitiveDataUtil.cardNoDesensitization(dto.getCardNo()));
            dto.setAccountName(SensitiveDataUtil.accountNameDesensitization(dto.getAccountName()));
        }
        PageInfo<MerchantCashOutDTO> pageInfo = new PageInfo<>(list);
        PageDTO dto = BeanConvertUtils.convert(pageInfo, PageDTO.class);
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "提现记录查询成功", dto);
    }

    /**
     * 查询出商户的支付产品
     *
     * @param custom
     * @return
     */
    @PostMapping("/selectPayProduct")
    public CommonResult<List<PaymentProduct>> selectPayProduct(@RequestBody MerchantSettleRateCustomCriteria custom) {
        List<PaymentProduct> productList = merchantSettleRateCustomService.selectAll(custom);
        return new CommonResult<List<PaymentProduct>>(CommonConstants.RETURN_SUCCESS, "支付产品查询成功", productList);
    }

    /**
     * 今日交易汇总查询
     *
     * @param merchantDTO
     * @return
     */
    @PostMapping("/todaySum")
    public CommonResult<ChargeOrderResponseDTO> todaySum(MerchantDTO merchantDTO) {
        Date currentDate = DateUtils.getNowDate();
        Integer dateInteger = DateUtils.dateToInteger(currentDate);
        ChargeOrderResponseDTO dto = new ChargeOrderResponseDTO();
        OrderInfoCriteria cri = new OrderInfoCriteria();
        cri.setMerchantId(merchantDTO.getId());
        cri.setOrderGenerateTimeIndexStart(dateInteger);
        cri.setOrderGenerateTimeIndexEnd(dateInteger);
        dto = orderService.selectSumAmountAndFee(cri);
        dto.setPlatformTotalIncome(null);
        dto.setProxyTotalIncome(null);
        if (merchantDTO.getMerchantType().equals("PROXY")) {
            OrderInfoCriteria cri2 = new OrderInfoCriteria();
            cri2.setProxyId(merchantDTO.getId());
            cri2.setOrderGenerateTimeIndexStart(dateInteger);
            cri2.setOrderGenerateTimeIndexEnd(dateInteger);
            ChargeOrderResponseDTO dto2 = orderService.selectSumAmountAndFee(cri2);
            if (dto2.getProxyTotalIncome() != null) {
                BigDecimal decimal = dto.getMerchantTotalIncome() == null ? BigDecimal.ZERO : dto.getMerchantTotalIncome();
                dto.setMerchantTotalIncome(decimal.add(dto2.getProxyTotalIncome()));
            }
        }
        int sum = partitionService.selectPartSum(merchantDTO.getId());
        dto.setPartitionNum(sum);
        // 查询昨日充值金额、充值笔数、充值收入金额
        Date dayBeforeDay = DateUtils.getDayTimeBeforeDay(1);
        Integer s3 = DateUtils.dateToInteger(dayBeforeDay);
        OrderInfoCriteria temp = new OrderInfoCriteria();
        temp.setOrderGenerateTimeIndexStart(s3);
        temp.setOrderGenerateTimeIndexEnd(s3);
        temp.setMerchantId(merchantDTO.getId());
        ChargeOrderResponseDTO amountAndFee = orderService.selectSumAmountAndFee(temp);
        BigDecimal zero = new BigDecimal(0);
        dto.setYesterdayTotal(amountAndFee.getSuccessTotal() == null ? 0L : amountAndFee.getSuccessTotal());
        dto.setYesterdayTotalAmount(amountAndFee.getSuccessTotalAmount() == null ? zero : amountAndFee.getSuccessTotalAmount());
        dto.setYesterdayMerchantTotalIncome(amountAndFee.getMerchantTotalIncome() == null ? zero : amountAndFee.getMerchantTotalIncome());
        dto.setYesterdayPlatformTotalIncome(amountAndFee.getPlatformTotalIncome() == null ? zero : amountAndFee.getPlatformTotalIncome());
        if (merchantDTO.getMerchantType().equals("PROXY")) {
            OrderInfoCriteria cri2 = new OrderInfoCriteria();
            cri2.setOrderGenerateTimeIndexStart(s3);
            cri2.setOrderGenerateTimeIndexEnd(s3);
            cri2.setProxyId(merchantDTO.getId());
            ChargeOrderResponseDTO dto2 = orderService.selectSumAmountAndFee(cri2);
            if (dto2.getProxyTotalIncome() != null) {
                BigDecimal decimal = dto.getYesterdayMerchantTotalIncome() == null ? BigDecimal.ZERO : dto.getYesterdayMerchantTotalIncome();
                dto.setYesterdayMerchantTotalIncome(decimal.add(dto2.getProxyTotalIncome()));
            }
        }
        dto.setTodySettledAmt(BigDecimal.ZERO);
        MerchantCashOutCriteria selectCriteria=new MerchantCashOutCriteria();
        selectCriteria.setTradeStatus(3);
        selectCriteria.setMerchantId(merchantDTO.getId());
        String currentDateStartTimeStr = DateUtils.dateToString(currentDate, "yyyy-MM-dd 00:00:00");
        String currentDateEndTimeStr = DateUtils.dateToString(currentDate, "yyyy-MM-dd 23:59:59");
        selectCriteria.setStratTime(DateUtils.stringToDate2(currentDateStartTimeStr));
        selectCriteria.setEndTime(DateUtils.stringToDate2(currentDateEndTimeStr));
        selectCriteria.setIsAtuoSettle(2);
        MerchantCashOutCountDTO todySettledAmtDTO=merchantCashOutService.countMerchantCashOutAll(selectCriteria);
        if (todySettledAmtDTO != null){
            BigDecimal todySettleAmt = todySettledAmtDTO.getCountSellteAmount();
            todySettleAmt =todySettleAmt==null?BigDecimal.ZERO:todySettleAmt;
            dto.setTodySettledAmt(todySettleAmt);
        }
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "今日交易汇总查询成功", dto);
    }

    /**
     * 充值统计
     *
     * @param merchantDTO
     * @return
     */
    @PostMapping("/topUpStatistics")
    public CommonResult<StatisticsPageDTO> topUpStatistics(MerchantDTO merchantDTO,@RequestBody StatisticsCriteria statistics) {
        statistics.setMerchantId(merchantDTO.getId());
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "商户统计查询成功",orderService.topUpStatistics(statistics));
    }

    /**
     * 获取网站设置
     *
     * @return
     */
    @GetMapping("/netConfig")
    public CommonResult<NetConfigDTO> netConfig() {
        NetConfigDTO netConfigDTO = netConfigService.getNetConfigDTO();
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "成功", netConfigDTO);
    }

    @GetMapping("/dowPayUrls")
    public void downFile(HttpServletResponse response,HttpServletRequest req) {
        String merchantId =req.getParameter("merchantId");
        String groupId =req.getParameter("groupId");
        if (StringUtils.isBlank(merchantId)) {
            throw new ParameterException("商户id不能为空");
        }
        List<NetRechargeUrl> rechargeUrls = netRechargeUrlService.selectAll();
        for (NetRechargeUrl rechargeUrl : rechargeUrls) {
            String url = rechargeUrl.getUrl() + "/gws/checkGroup.html?m=" + merchantId;
            if (StringUtils.isNotEmpty(groupId)) {
                url += "&g=" + groupId;
            }
            rechargeUrl.setUrl(url);
        }
        Context context = new Context();
        context.setVariable("rechargeUrls", rechargeUrls);
        String fileName = "PayUrls-" + DateUtils.dateToString(new Date(), DateUtils.formatPattern) + ".html";
        templateUtils.exportHTML("PayUrls", fileName, context, response);
    }

    /**
     * 设置支付密码
     *
     * @param merchantCriteria
     * @return
     */
    @PostMapping("/setPayPassword")
    public CommonResult setPayPassword(MerchantDTO merchantDTO, @RequestBody MerchantCriteria merchantCriteria) {
        if (StringUtils.isBlank(merchantCriteria.getCode())) {
            throw new ParameterException("短信验证码不能为空");
        }
        merchantCriteria.setId(merchantDTO.getId());
        Merchant merchant = merchantService.find(merchantDTO.getId());
        String code = redisCacheUtil.getObjectFromCache(SMSType.RESET_PAY_PASSWORD.name() + merchant.getPhone());
        if (!merchantCriteria.getCode().equalsIgnoreCase(code)) {
            return new CommonResult(CommonConstants.RETURN_ERROR, "短信验证码输入错误");
        }
        if (merchantService.setPayPassword(merchantCriteria)) {
            return new CommonResult(CommonConstants.RETURN_SUCCESS, "设置支付密码成功");
        }
        return new CommonResult(CommonConstants.RETURN_ERROR, "设置支付密码失败");
    }

    /**
     * 发送短信验证码
     *
     * @return
     */
    @PostMapping("/sms")
    public CommonResult sms(@CookieValue("codeKey") String codeKey, @RequestBody MerchantCriteria merchantCriteria
            , MerchantDTO merchantDTO) {
        if (StringUtils.isBlank(merchantCriteria.getCode())) {
            throw new ParameterException("图片验证码不能为空");
        }
        String code = redisCacheUtil.getObjectFromCache(codeKey);
        //验证验证码
        if (!merchantCriteria.getCode().equalsIgnoreCase(code)) {
            return new CommonResult(CommonConstants.RETURN_ERROR, "图片验证码输入错误");
        }
        Merchant merchant = merchantService.find(merchantDTO.getId());
        String temp = "";
        if (merchantCriteria.getSmsType().equals(SMSType.BIND_MOBILE)) {
            if (StringUtils.isBlank(merchantCriteria.getPhone())) {
                throw new ParameterException("手机号不能为空");
            }
            temp = merchantCriteria.getPhone();
        } else {
            if (StringUtils.isBlank(merchant.getPhone())) {
                return new CommonResult(CommonConstants.RETURN_ERROR, "短信验证码成功失败，请先绑定手机号");
            }
            temp = merchant.getPhone();
        }
        smsUtil.send(temp, merchantCriteria.getSmsType(), merchant.getId());
        String phone = SensitiveDataUtil.mobileEncrypt(merchantDTO.getPhone());
        return new CommonResult(CommonConstants.RETURN_SUCCESS, "短信验证码成功发送到:" + phone, phone);
    }

    /**
     * 绑定手机号
     *
     * @param merchantCriteria
     * @return
     */
    @PostMapping("/bindMobile")
    public CommonResult bindMobile(MerchantDTO merchantDTO, @RequestBody MerchantCriteria merchantCriteria) {
        if (StringUtils.isBlank(merchantCriteria.getCode())) {
            throw new ParameterException("短信验证码不能为空");
        }
        if (StringUtils.isBlank(merchantCriteria.getPhone())) {
            throw new ParameterException("手机号不能为空");
        }
        String code = redisCacheUtil.getObjectFromCache(SMSType.BIND_MOBILE.name() + merchantCriteria.getPhone());
        if (!merchantCriteria.getCode().equalsIgnoreCase(code)) {
            return new CommonResult(CommonConstants.RETURN_ERROR, "短信验证码输入错误");
        }
        Merchant db = merchantService.find(merchantDTO.getId());
        if (StringUtils.isNotBlank(db.getPhone())) {
            return new CommonResult(CommonConstants.RETURN_ERROR, "请先解绑手机号");
        }
        Merchant merchant = new Merchant();
        merchant.setPhone(merchantCriteria.getPhone());
        merchant.setId(merchantDTO.getId());
        if (merchantService.update(merchant)) {
            return new CommonResult(CommonConstants.RETURN_SUCCESS, "绑定手机号成功");
        }
        return new CommonResult(CommonConstants.RETURN_ERROR, "绑定手机号失败");
    }

    /**
     * 解绑手机号
     *
     * @param merchantCriteria
     * @return
     */
    @PostMapping("/untieMobile")
    public CommonResult untieMobile(MerchantDTO merchantDTO, @RequestBody MerchantCriteria merchantCriteria) {
        if (StringUtils.isBlank(merchantCriteria.getCode())) {
            throw new ParameterException("短信验证码不能为空");
        }
        Merchant merchant = merchantService.find(merchantDTO.getId());
        String code = redisCacheUtil.getObjectFromCache(SMSType.UNTIE_MOBILE.name() + merchant.getPhone());
        if (!merchantCriteria.getCode().equalsIgnoreCase(code)) {
            return new CommonResult(CommonConstants.RETURN_ERROR, "短信验证码输入错误");
        }
        if (merchantService.untieMobile(merchantDTO.getId())) {
            return new CommonResult(CommonConstants.RETURN_SUCCESS, "解绑手机号成功");
        }
        return new CommonResult(CommonConstants.RETURN_ERROR, "解绑手机号失败");
    }

    /**
     * 查询留言箱状态
     *
     * @param criteria
     * @return
     */
    @PostMapping("/msgStatus")
    public CommonResult<MerchantConfig> selectRateInfo(@RequestBody PartitionCriteria criteria) {
        MerchantConfig merchantConfig = merchantConfigService.selectMsgStatus(criteria);
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "查询留言箱状态成功", merchantConfig);
    }

    /**
     * 查询商户支付宝代付配置信息
     *
     * @param merchantDTO
     * @return
     */
    @GetMapping("/getAliPayConfig")
    public CommonResult<MerchantAlipayConfigDTO> getAliPayConfig(MerchantDTO merchantDTO) {
        MerchantAlipayConfigDTO config = merchantAlipayConfigService.getConfigByMerchantId(merchantDTO.getId());
        config.setPublicCertBase64(null);
        config.setRootCertBase64(null);
        config.setAlipayPublicCertBase64(null);
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "查询商户支付宝代付配置信息成功", config);
    }

    /**
     * 证书文件上传
     *
     * @param file 证书文件
     * @param type 证书类型
     * @return
     */
    @PostMapping("/uploadCrt")
    public CommonResult<Object> bathPay(MerchantDTO merchantDTO, @RequestParam(value = "file") MultipartFile file,
                                        @RequestParam(value = "type") String type) {
        String traceId = SnowFlakeUtils.getTraceId();
        if (file == null) {
            throw new ParameterException("证书不能为空");
        }
        if (StringUtils.isEmpty(type)) {
            throw new ParameterException("证书类型不能为空");
        }
        String fileName = file.getOriginalFilename();
        String suffixName = "";
        if (StringUtils.isNotBlank(fileName)) {
            suffixName = fileName.substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        }
        suffixName = suffixName.toLowerCase();
        if (!"crt".equals(suffixName)) {
            LogPortal.error("{} 商户[{}]上传证书文件失败，文件格式错误，仅支持crt，当前文件格式：{}", traceId, merchantDTO.getId(), suffixName);
            throw new ParameterException("文件格式错误，仅支持crt格式证书");
        }
        try {
            String base64Str = Base64.encode(file.getBytes());
            MerchantAlipayConfigDTO dto = new MerchantAlipayConfigDTO();
            dto.setMerchantId(merchantDTO.getId());
            switch (type) {
                case "root":
                    dto.setRootCertName(fileName);
                    dto.setRootCertBase64(base64Str);
                    break;
                case "public":
                    dto.setPublicCertName(fileName);
                    dto.setPublicCertBase64(base64Str);
                    break;
                case "alipay":
                    dto.setAlipayPublicCertName(fileName);
                    dto.setAlipayPublicCertBase64(base64Str);
                    break;
                default:
                    throw new ParameterException("证书类型错误");
            }
            if (merchantAlipayConfigService.updateConfig(dto)) {
                return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "上传成功", fileName);
            }
        } catch (Exception e) {
            LogPortal.error("{} 商户[{}]上传证书文件失败,发生[{}]异常，异常内容为[{}]", traceId, merchantDTO.getId(),
                    e.getClass().getName(), e.getMessage());
        }
        return new CommonResult<>(CommonConstants.RETURN_ERROR, "上传失败");
    }

    /**
     * 更新商户支付宝代付配置信息
     *
     * @param dto
     * @return
     */
    @PostMapping("/updateAliPayConfig")
    public CommonResult<MerchantAlipayConfigDTO> updateAliPayConfig(MerchantDTO merchantDTO, @RequestBody MerchantAlipayConfigDTO dto) {
        dto.setMerchantId(merchantDTO.getId());
        dto.setStatus(null);
        if (merchantAlipayConfigService.updateConfig(dto)) {
            return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "更新商户支付宝代付配置信息成功");
        }
        return new CommonResult<>(CommonConstants.RETURN_ERROR, "更新商户支付宝代付配置信息失败");
    }

    /**
     * 增加支付宝代付订单
     *
     * @param dto
     * @return
     */
    @PostMapping("/addAliPay")
    public CommonResult<Object> addAliPay(MerchantDTO merchantDTO, @RequestBody MerchantAlipayOrderDTO dto) {
        if (StringUtils.isEmpty(dto.getName())) {
            throw new ParameterException("收款人不能为空");
        }
        if (StringUtils.isEmpty(dto.getAccountNo())) {
            throw new ParameterException("收款账号不能为空");
        } else if (!Validator.isMobile(dto.getAccountNo()) && !Validator.isEmail(dto.getAccountNo())) {
            throw new ParameterException("收款账号格式错误，只支持手机号或邮箱");
        }
        if (dto.getTransAmount() == null) {
            throw new ParameterException("支付金额不能为空");
        }
        if (dto.getTransAmount().compareTo(BigDecimal.ZERO) <= 0) {
            throw new ParameterException("支付金额必须大于0");
        }
        dto.setMerchantId(merchantDTO.getId());
        if (merchantAlipayOrderService.addAliPayOrder(dto)) {
            return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "添加支付宝代付成功");
        }
        return new CommonResult<>(CommonConstants.RETURN_ERROR, "添加支付宝代付失败");
    }

    /**
     * 查询支付宝代付订单的状态
     *
     * @param merchantOrderNo
     * @return
     */
    @GetMapping("/queryAliPay")
    public CommonResult<Object> queryAliPay(MerchantDTO merchantDTO, @RequestParam("merchantOrderNo") String merchantOrderNo) {
        if (StringUtils.isEmpty(merchantOrderNo)) {
            throw new ParameterException("商户订单号不能为空");
        }
        MerchantAlipayOrderDTO dto = new MerchantAlipayOrderDTO();
        dto.setTraceId(SnowFlakeUtils.getTraceId());
        dto.setMerchantId(merchantDTO.getId());
        dto.setMerchantOrderNo(merchantOrderNo);
        aliPayService.queryOrderStatus(dto);
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "查询成功");
    }

    /**
     * 一键查询支付宝代付订单的状态
     *
     * @param merchantDTO
     * @return
     */
    @GetMapping("/queryAllAliPay")
    public CommonResult<Object> queryAllAliPay(MerchantDTO merchantDTO) {
        MerchantAlipayOrderCriteria criteria = new MerchantAlipayOrderCriteria();
        criteria.setMerchantId(merchantDTO.getId());
        criteria.setStatus(AliOrderStatus.PROCESSING.getCode());
        List<MerchantAlipayOrderDTO> list = merchantAlipayOrderService.list(criteria);
        for (MerchantAlipayOrderDTO dto : list) {
            dto.setTraceId(SnowFlakeUtils.getTraceId());
            aliPayService.queryOrderStatus(dto);
        }
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "一键查询成功");
    }

    /**
     * 查询GM游戏公告内容
     * @param criteria
     * @return
     */
    @PostMapping("/getMerchantNotice")
    public CommonResult<String> getMerchantNotice(@RequestBody PartitionCriteria criteria) {
        if ("2".equals(criteria.getSelectType())){ //商户ID
            if (StringUtils.isEmpty(criteria.getId())){
                return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "商户ID不能为空","");
            }
            MerchantConfig merchantConfig = merchantConfigService.selectOne(Integer.valueOf(criteria.getId()));
            if (merchantConfig == null){
                return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "商户记录不存在","");
            }
            return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "查询GM游戏公告成功",merchantConfig.getSkillQq());
        } else {
            if (StringUtils.isEmpty(criteria.getPartitionId())){
                return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "分区ID不能为空","");
            }
            MerchantConfigDTO merchantConfig = merchantConfigService.getMerchantConfigByPartitionId(criteria.getPartitionId());
            if (merchantConfig == null){
                return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "分区ID不存在","");
            }
            return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "查询GM游戏公告成功",merchantConfig.getSkillQq());
        }
    }

    /**
     * 获取绑定微信二维码
     *
     * @param merchantDTO
     * @return
     */
    @GetMapping("/getQrCode")
    public CommonResult<Object> getQrCode(MerchantDTO merchantDTO) {
        WxUser bindWxUser = wxUserService.getBindWxUser(merchantDTO.getId(), merchantDTO.getLoginId());
        if (bindWxUser == null) {
            WxConfig config = wxConfigService.getConfig();
            if (config.getStatus() == 0) {
                return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "微信公众号功能暂未开启","");
            }
            WxQrCode qrCode = wxQrCodeService.getQrCodeByMerchantId(merchantDTO);
            try {
                String url = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + URLEncoder.encode(qrCode.getTicket()
                        , "UTF-8");
                return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "获取成功", url);
            } catch (Exception e) {
                String traceId = SnowFlakeUtils.getTraceId();
                throw new LogicalException("[{}]用户[{}]获取微信公众号二维码url失败,发生[{}]异常,异常信息为[{}]", traceId, merchantDTO.getId(),
                        e.getClass().getSimpleName(), e.getMessage());
            }
        } else {
            return new CommonResult<>(199, "获取成功", bindWxUser);
        }
    }

    /**
     * 获取解绑微信二维码
     *
     * @param key
     * @return
     */
    @GetMapping("/getUnBindQrCode")
    public void getUnBindQrCode(@RequestParam("key") String key, MerchantDTO merchantDTO, HttpServletResponse response) {
        if (StringUtils.isEmpty(key)) {
            throw new ParameterException("key不能为空");
        }
        if (!key.contains("unBind-")) {
            throw new ParameterException("key格式错误");
        }
        try {
            redisCacheUtil.setObjectToCache("WX_UN_BIND:" + key, merchantDTO, 300L, TimeUnit.SECONDS);
            WxConfig wxConfig = wxConfigService.getConfig();
            if (wxConfig.getStatus() == 0) {
                return;
            }
            String uri = URLEncoder.encode(wxConfig.getNetUrl() + "/static/wx/unBind.html?", "utf-8");
            String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wxConfig.getAppId() +
                    "&redirect_uri=" + uri + "&response_type=code&scope=snsapi_base&state=" + key + "#wechat_redirect";
            QrCodeUtils.encode(url, response.getOutputStream());
        } catch (Exception e) {
            String traceId = SnowFlakeUtils.getTraceId();
            throw new LogicalException("[{}]key[{}]获取解绑微信二维码url失败,发生[{}]异常,异常信息为[{}]", traceId, key,
                    e.getClass().getSimpleName(), e.getMessage());
        }
    }

    /**
     * 获取解绑微信二维码的扫描状态
     *
     * @param key
     * @return
     */
    @GetMapping("/getUnBindStatus")
    public CommonResult<Object> getUnBindStatus(@RequestParam("key") String key) {
        if (StringUtils.isEmpty(key)) {
            throw new ParameterException("key不能为空");
        }
        if (!key.contains("unBind-")) {
            throw new ParameterException("key格式错误");
        }
        Integer status = redisCacheUtil.getObjectFromCache("WX_UN_BIND_STATUS:" + key);
        if (status == null) {
            status = 0;
        }
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "获取成功", status);
    }

    /**
     * 获取关注的微信信息列表
     *
     * @param merchantDTO
     * @return
     */
    @GetMapping("/getWxList")
    public CommonResult<Object> getWxList(MerchantDTO merchantDTO) {
        List<WxUserDTO> wxList = wxUserService.getWxList(merchantDTO);
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "获取关注的微信信息成功", wxList);
    }

    /**
     * 更改是否接收异常消息提醒状态
     *
     * @param wxUserDTO
     * @return
     */
    @PostMapping("/updateWxMsgStatus")
    public CommonResult<Object> updateWxMsgStatus(@RequestBody WxUserDTO wxUserDTO) {
        wxUserService.updateWxMsgStatus(wxUserDTO);
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "修改成功");
    }

    /**
     * 获取登录微信二维码
     *
     * @param key
     * @return
     */
    @GetMapping("/getLoginQrCode")
    public void getLoginQrCode(@RequestParam("key") String key, HttpServletResponse response) {
        if (StringUtils.isEmpty(key)) {
            throw new ParameterException("key不能为空");
        }
        if (!key.contains("qrToken-")) {
            throw new ParameterException("key格式错误");
        }
        try {
            WxConfig wxConfig = wxConfigService.getConfig();
            if (wxConfig.getStatus() == 0) {
                return;
            }
            String uri = URLEncoder.encode(wxConfig.getNetUrl() + "/static/wx/fixLogin.html", "utf-8");
            String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wxConfig.getAppId() +
                    "&redirect_uri=" + uri + "&response_type=code&scope=snsapi_base&state=" + key + "#wechat_redirect";
            QrCodeUtils.encode(url, response.getOutputStream());
        } catch (Exception e) {
            String traceId = SnowFlakeUtils.getTraceId();
            throw new LogicalException("[{}]key[{}]获取登录微信二维码url失败,发生[{}]异常,异常信息为[{}]", traceId, key,
                    e.getClass().getSimpleName(), e.getMessage());
        }
    }

    /**
     * 扫码登录商户
     *
     * @param merchantCriteria
     * @return
     */
    @PostMapping("/qrCodeLogin")
    public CommonResult<Map<String, Object>> qrCodeLogin(@RequestBody MerchantCriteria merchantCriteria,
                                                         HttpServletRequest request) {
        if (StringUtils.isEmpty(merchantCriteria.getKey())) {
            throw new ParameterException("登录key不能为空");
        }
        if (!merchantCriteria.getKey().contains("qrToken-")) {
            throw new ParameterException("key格式错误");
        }
        QrToken qrToken = redisCacheUtil.getObjectFromCache("QR-CODE-LOGIN-TOKEN:" + merchantCriteria.getKey());
        if (qrToken == null) {
            return new CommonResult<>(196, "登录失败,登录信息不存在");
        }
        LogPortal.info("登录信息QrToken:[{}]", JSON.toJSONString(qrToken));
        Map<String, Object> result = new HashMap<>(16);
        if (qrToken.getStatus() == 0) {
            result.put("openid", qrToken.getOpenid());
            return new CommonResult<>(197, "登录失败,请先关注微信公众号", result);
        } else if (qrToken.getStatus() == 1) {
            return new CommonResult<>(198, "请在微信确认登录");
        } else if (qrToken.getStatus() == 2) {
            return new CommonResult<>(199, "已在微信拒绝");
        }
        String loginAccount = "";
        if (LoginType.FATHER.name().equals(qrToken.getLoginType())) {
            Merchant merchant = merchantService.find(qrToken.getMerchantId());
            if (merchant == null) {
                return new CommonResult<>(CommonConstants.RETURN_ERROR, "进入商户后台失败，不存在此商户");
            }
            loginAccount = merchant.getLoginAccount();
            result.put("merchantStatus", merchant.getStatus().name());
            result.put("merchantType", merchant.getMerchantType());
            MerchantPermissionDTO dto = merchantPermissionService.adminList(merchant.getMerchantType());
            result.put("permission", dto);
        } else {
            MerchantSon merchantSon = merchantSonService.selectInfo(qrToken.getLoginId());
            if (merchantSon == null) {
                return new CommonResult<>(CommonConstants.RETURN_ERROR, "进入商户后台失败，不存在此商户");
            }
            loginAccount = merchantSon.getLoginAccount();
            MerchantPermissionDTO dto = merchantPermissionService.sonPermissionList(merchantSon.getRoleId());
            result.put("permission", dto);
        }
        String ip = IPUtils.getIp(request);
        Token token = tokenService.createToken(qrToken.getMerchantId(), qrToken.getLoginId(), qrToken.getLoginType(),ip);
        result.put("accessToken", token.getAccessToken());
        result.put("loginType", "oneself");
        NetConfigDTO netConfig = netConfigService.getNetConfig();
        result.put("domainName", netConfig.getDomainName());
        result.put("type", qrToken.getLoginType());
        addLoginHistory(qrToken.getLoginId(), request);
        wxSendMsgUtils.login(qrToken.getMerchantId(), qrToken.getLoginId(), loginAccount,
                "微信（" + qrToken.getWxName() + "）扫码登录",ip);
        return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "登录成功", result);
    }

    /**
     * 绑定微信
     *
     * @param merchantCriteria
     * @param request
     * @return
     */
    @PostMapping("/bindWx")
    public CommonResult<Map<String, Object>> bindWx(@RequestBody MerchantCriteria merchantCriteria, HttpServletRequest request) {
        if (StringUtils.isEmpty(merchantCriteria.getOpenid())) {
            throw new ParameterException("openid不能为空");
        }
        MerchantLoginDTO loginDTO = merchantService.login(merchantCriteria);
        WxUser wxUser = new WxUser();
        wxUser.setOpenid(merchantCriteria.getOpenid());

        if (loginDTO.getType().equals(LoginType.FATHER.name())) {
            MerchantDTO merchant = loginDTO.getMerchant();
            wxUser.setMerchantId(merchant.getId());
            wxUser.setType(1);
            wxUser.setLoginId(merchant.getId());
            wxUser.setWxMsgStatus(1);
            if (wxUserService.bindWx(wxUser, merchantCriteria.getLoginAccount())) {
                //redis保存登录id
                Map<String, Object> result = saveFatherLogin(request, merchant);
                return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "绑定成功", result);
            } else {
                return new CommonResult<>(CommonConstants.RETURN_ERROR, "绑定失败，请先关注微信公众号");
            }
        } else if (loginDTO.getType().equals(LoginType.SON.name())) {
            MerchantSonDTO merchantSon = loginDTO.getMerchantSon();
            wxUser.setMerchantId(merchantSon.getMerchantId());
            wxUser.setLoginId(merchantSon.getId());
            wxUser.setWxMsgStatus(0);
            if (StringUtils.isNotBlank(merchantSon.getGroupId())) {
                wxUser.setType(3);
            } else {
                wxUser.setType(2);
            }
            if (wxUserService.bindWx(wxUser, merchantCriteria.getLoginAccount())) {
                //redis保存登录id
                Map<String, Object> result = saveSonLogin(request, merchantSon);
                return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "绑定成功", result);
            } else {
                return new CommonResult<>(CommonConstants.RETURN_ERROR, "绑定失败，请先关注微信公众号");
            }
        } else {
            return new CommonResult<>(CommonConstants.RETURN_ERROR, "绑定失败，登录错误");
        }
    }

    private Map<String, Object> saveFatherClientLogin(HttpServletRequest request, MerchantDTO merchant) {
        String clientType = request.getHeader("clientType");
        if (StringUtils.isEmpty(clientType)) {
            throw new ParameterException("客户端类型不能为空");
        }
        Token token=null;
        if(clientType.equals("gateWay")){
            token = tokenService.createToken(merchant.getId(), merchant.getId(), clientType);
        }
        Map<String, Object> result = new HashMap<>(16);
        result.put("accessToken", token.getAccessToken());
        result.put("loginOutTime", token.getLoginOutTime());
        result.put("merchantStatus", merchant.getStatus().name());
        result.put("merchantType", merchant.getMerchantType());
        result.put("loginType", "oneself");
        result.put("type", LoginType.FATHER.name());
        return result;
    }

    private Map<String, Object> saveFatherLogin(HttpServletRequest request, MerchantDTO merchant) {
        String ip = IPUtils.getIp(request);
        Token token = tokenService.createToken(merchant.getId(), merchant.getId(), LoginType.FATHER.name(),ip);
        addLoginHistory(merchant.getId(), request);
        Map<String, Object> result = new HashMap<>(16);
        result.put("accessToken", token.getAccessToken());
        result.put("loginOutTime", token.getLoginOutTime());
        result.put("merchantStatus", merchant.getStatus().name());
        result.put("merchantType", merchant.getMerchantType());
        result.put("loginType", "oneself");
        result.put("type", LoginType.FATHER.name());
        return result;
    }

    private Map<String, Object> saveSonLogin(HttpServletRequest request, MerchantSonDTO merchantSon) {
        //redis保存登录id
        String ip = IPUtils.getIp(request);
        Token token = tokenService.createToken(merchantSon.getMerchantId(), merchantSon.getId(), LoginType.SON.name(),ip);
        Map<String, Object> result = new HashMap<>(16);
        result.put("accessToken", token.getAccessToken());
        result.put("loginType", "oneself");
        if (StringUtils.isNotBlank(merchantSon.getGroupId())) {
            result.put("type", "TuiG");
        } else {
            result.put("type", LoginType.SON.name());
        }
        addLoginHistory(merchantSon.getId(), request);
        return result;
    }
    /**
     * 获取充值链接URL
     * @return
     */
    @GetMapping("/getRechargeUrl")
    public CommonResult getRechargeUrl(){
        List<NetRechargeUrl> rechargeUrls = netRechargeUrlService.selectAll();
        if (CollectionUtils.isEmpty(rechargeUrls)){
            return new CommonResult(CommonConstants.RETURN_ERROR, "充值链接必须设置",null);
        }
        rechargeUrls.forEach(item->{
            if (!item.getUrl().endsWith("/")){
                item.setUrl(item.getUrl().concat("/"));
            }
        });
        return new CommonResult(CommonConstants.RETURN_SUCCESS, "获取充值链接URL成功",rechargeUrls);
    }

    /**
     * 修改皮肤功能
     * @param merchantConfig
     * @param merchantDTO
     * @return
     */
    @PostMapping("/updateSkin")
    public CommonResult updateSkin(@RequestBody MerchantConfig merchantConfig, MerchantDTO merchantDTO) {
        merchantConfig.setMerchantId(merchantDTO.getId());
        if (merchantConfigService.updateSkin(merchantConfig)) {
            return new CommonResult(CommonConstants.RETURN_SUCCESS, "皮肤修改成功", null);
        }
        return new CommonResult(CommonConstants.RETURN_ERROR, "皮肤修改失败", null);
    }

    /**
     * 根据商户ID或分区ID查询充值皮肤
     * @param request
     * @return
     */
    @GetMapping("/getRechargeSkin")
    public CommonResult getRechargeSkin(HttpServletRequest request) {
        String type = request.getParameter("type");
        if ("0".equals(type)){ // 按照商户ID进行查询
            Integer merchantId = Integer.valueOf(request.getParameter("id"));
            MerchantConfig merchantConfig = merchantConfigService.selectOne(merchantId);
            if (merchantConfig != null){
                return new CommonResult(CommonConstants.RETURN_SUCCESS, "获取充值皮肤成功", merchantConfig.getRechargeSkin());
            }
        } else {
            String partitionId = request.getParameter("id");
            MerchantConfigDTO merchantConfigDTO = merchantConfigService.getMerchantConfigByPartitionId(partitionId);
            if (merchantConfigDTO != null){
                return new CommonResult(CommonConstants.RETURN_SUCCESS, "获取充值皮肤成功", merchantConfigDTO.getRechargeSkin());
            }
        }
        return new CommonResult(CommonConstants.RETURN_SUCCESS, "获取充值皮肤成功",1);
    }

    /**
     * 下载充值网关
     * @param response
     * @param merchantDTO
     */
    @PostMapping("/downRechargeGateWay")
    public void downRechargeGateWay(HttpServletResponse response,MerchantDTO merchantDTO) {
        if (merchantDTO==null) {
            throw new ParameterException("未登录，不能下载充值网关");
        }
       Integer merchantId = merchantDTO.getId();
       Merchant merchant = merchantService.find(merchantId);
       String merchantPubKey = merchant.getPublicKey();
       String path = xyRechargeGateWayPath;
       String fileName = "PayGateway.ini";
        StringBuffer dataStr = new StringBuffer("[SYS]\nkey=").append(merchantPubKey).append("\nport=6777");
        LogPortal.debug("下载充值网关 根目录:{}",path);
        FileUtils.writeData(path,fileName,dataStr.toString());
        String zipDestPath =path.substring(0,path.lastIndexOf(File.separator));
        String zipFileName = "PayGateway".concat(String.valueOf(merchantId)).concat(".zip");
        try {
            LogPortal.debug("下载充值网关 压缩目的目录:{}",zipDestPath);
            ZipUtils.zip(path,zipDestPath,zipFileName,false);
        } catch (Exception e) {
            LogPortal.error("压缩充值网关发生{}异常",e,e.getClass().getName());
            throw new ParameterException("充值网关压缩发生异常");
        }
        InputStream ins = null;
        OutputStream ous = null;
        try {
            File file = new File(zipDestPath.concat("/").concat(zipFileName));
            ins = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[ins.available()];
            ins.read(buffer);
            response.reset();
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(file.getName().getBytes()));
            response.addHeader("Content-Length", "" + file.length());
            ous = new BufferedOutputStream(response.getOutputStream());
            response.setContentType("application/octet-stream");
            ous.write(buffer);
            ous.flush();
        } catch (Exception e) {
            LogPortal.error("下载充值网关发生{}异常",e,e.getClass().getName());
            throw new ParameterException("充值网关下载发生异常");
        } finally {
            if (ins != null) {
                try {
                    ins.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ous != null) {
                try {
                    ous.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 文件上传
     */
    @ResponseBody
    @RequestMapping(method = RequestMethod.POST, value = "/uploadImg")
    public CommonResult<String> upload(@RequestParam("file") MultipartFile file, MerchantDTO merchantDTO) {
        String traceId = SnowFlakeUtils.getUniqueId();
        String suffix = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        if (!"jpg".equalsIgnoreCase(suffix) && !"png".equalsIgnoreCase(suffix) && !"jpeg".equalsIgnoreCase(suffix) && !"gif".equalsIgnoreCase(suffix)) {
            LogPortal.error("{} 商户[{}]图片上传失败，文件格式错误，仅支持jpg、png、jpeg、gif，当前文件格式：{}", traceId, merchantDTO.getId(), suffix);
            throw new ParameterException("上传失败，图片格式错误，仅支持jpg、png、jpeg、gif格式");
        }
        if (file.getSize() > 1024 * 11000) {
            return new CommonResult<>(CommonConstants.RETURN_ERROR, "图片过大，仅支持10M之下的图片");
        }
        suffix = suffix.toLowerCase();
        String fileName = traceId.concat(".").concat(suffix);
        try {
            FtpUtil.uploadXYFile(file.getBytes(), fileName, "",traceId);
            return new CommonResult<>(CommonConstants.RETURN_SUCCESS, "上传成功", fileName);
        } catch (Exception e) {
            LogPortal.error("[{}]图片上传发生[{}]异常,异常信息为[{}]", e, traceId, e.getClass().getSimpleName(), e.getMessage());
            return new CommonResult<>(CommonConstants.RETURN_ERROR, "上传失败，错误码：" + traceId);
        }
    }

    /**
     * 文件下载
     *
     * @param fileName
     * @return
     */
    @ResponseBody
    @RequestMapping(method = RequestMethod.GET, value = "/downloadImg")
    public void downloadFile(HttpServletResponse response, @RequestParam("fileName") String fileName) {
        String traceId = SnowFlakeUtils.getUniqueId();
        ServletOutputStream outputStream = null;
        try {
            byte[] bytes = FtpUtil.downloadXYFile("", fileName);
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
            response.setHeader("Cache-Control", "No-cache");
            outputStream = response.getOutputStream();
            outputStream.write(bytes);
        } catch (Exception e) {
            LogPortal.error("[{}]文件下载发生[{}]异常,异常信息为[{}]", e, traceId, e.getClass().getSimpleName(), e.getMessage());
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.flush();
                    outputStream.close();
                }
            } catch (IOException e) {
                LogPortal.error("文件上传关闭流时发生IOException，异常信息为: {}", e, e.getMessage());
            }
        }
    }

    /**
     * 修改商户配置信息
     * @param merchantConfigDTO
     * @param merchantDTO
     * @return
     */
    @PostMapping("/updateMerchantConfig")
    public CommonResult updateQQ(@RequestBody MerchantConfigDTO merchantConfigDTO, MerchantDTO merchantDTO) {
        merchantConfigDTO.setMerchantId(merchantDTO.getId());
        if (merchantConfigService.updateMerchantConfig(merchantConfigDTO)) {
            return new CommonResult(CommonConstants.RETURN_SUCCESS, "修改成功", null);
        }
        return new CommonResult(CommonConstants.RETURN_ERROR, "修改失败", null);
    }

    /**
     * 商户操作记录查询
     *
     * @param merchantDTO
     * @return
     */
    @PostMapping("/operation")
    public CommonResult<PageDTO> logOperation(@RequestBody LogOperationCriteria logOperationCriteria, MerchantDTO merchantDTO) {
        logOperationCriteria.setMerchantId(merchantDTO.getId());
        PageHelper.startPage(logOperationCriteria.getPageNum(), logOperationCriteria.getPageSize());
        List<LogOperationDTO> logOperationList = logOperationService.selectAll(logOperationCriteria);
        PageInfo<LoginHistory> pageInfo = new PageInfo(logOperationList);
        PageDTO dto = BeanConvertUtils.convert(pageInfo, PageDTO.class);
        return new CommonResult<PageDTO>(CommonConstants.RETURN_SUCCESS, "登录记录查询成功", dto);
    }
}
